import {
  Form,
  Input,
  DatePicker,
  Select,
  Row,
  Col,
  InputNumber,
  Upload,
  message,
  Radio,
  TreeSelect,
  Button,
  AutoComplete,
  Image,
  Cascader,
  ConfigProvider,
  Tooltip,
} from 'antd';
import moment from 'moment';
import React, { useEffect, memo, useState } from 'react';
import { LoadingOutlined, UploadOutlined, RetweetOutlined } from '@ant-design/icons';
import UploadCom from '../UploadCom';
import mockfile from './mockfile.js';
import zhCN from 'antd/lib/locale/zh_CN';
import StrengthPwd from '../StrengthPwd';

moment.locale('zh-cn');

const { TreeNode } = TreeSelect;
const { RangePicker } = DatePicker;
let { Option } = Select;

let loop = (data, title, key, children) =>
  data &&
  data?.length > 0 &&
  data?.map((item) => {
    let defaulttitle = title ? title : 'title',
      defaultkey = key ? key : 'key',
      defaultchildren = children ? children : 'children';
    const titles = <span>{item[defaulttitle]}</span>;
    if (item[defaultchildren]) {
      return (
        <TreeNode value={item[defaultkey]} key={item[defaultkey]} title={titles}>
          {loop(item[defaultchildren])}
        </TreeNode>
      );
    } else {
      return <TreeNode value={item[defaultkey]} key={item[defaultkey]} title={titles} />;
    }
  });

function filter(inputValue, path) {
  return path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
}

function formartData(item, val) {
  let formartValue = val;
  if (item.type == 'upload') {
    let stepval = val ? (Array.isArray(val) ? val : val.fileList) : [];
    formartValue = stepval.map((it) => {
      if (it.response) {
        return it?.response?.data?.dataList ? it?.response?.data?.dataList[0] : [];
      } else {
        return it ? it : null;
      }
    });
    // if (item.limit == 1) {
    //   formartValue = formartValue[0] ? formartValue[0] : '';
    // }
  } else if (item.type == 'datepicker') {
    formartValue = val ? val.format(item.format ? item.format : 'YYYY-MM-DD') : null;
  } else if (item.type == 'daterange') {
    formartValue =
      val && Array.isArray(val)
        ? val.map((it) => (it ? moment(it).format(item.format ? item.format : 'YYYY-MM-DD') : null))
        : [];
  }
  return formartValue;
}

let InitForm = ({
  fields,
  onChange,
  submitting,
  submitData,
  actions,
  col,
  mode,
  formRef,
  style,
  reset,
  row,
  rowCol,
  autoSubmit,
  layout,
  children,
}) => {
  let [Dom, cDom] = useState([]),
    [cururl, setcururl] = useState(''),
    [loading, sload] = useState(false),
    [form] = Form.useForm(),
    [filelist, cfilelist] = useState({}),
    [link, clink] = useState({}),
    [belink, cbelink] = useState({}),
    [visible, setVisible] = useState(false),
    [optiondom, cdom] = useState({}),
    [len, clen] = useState(0),
    [ind, cind] = useState(0);

  form = formRef ? formRef : form;

  useEffect(() => {
    let Doms = [],
      klink = {},
      belinked = {},
      defaultfiles = {},
      allenin = 0;

    for (let i in fields) {
      let record = { ...fields[i] };
      if (record.defaultValueIndex || record.defaultValueIndex === 0) {
        allenin++;
      }
      //获取linked key
      if (record.linked === true) {
        klink[i] = record.value;
      }
      //获取belinked key
      if (record.belinked) {
        belinked[i] = record.belinked;
      }
      //初始化filelist
      if (record.type === 'upload') {
        let curfileList = record.value
          ? mockfile(Array.isArray(record.value) ? record.value : [record.value])
          : [];
        //default value

        defaultfiles[i] = curfileList ? (curfileList.fileList ? curfileList.fileList : []) : [];
        //formart value
        record.value = curfileList;
      } else if (record.type === 'datepicker') {
        record.value = record.value ? moment(record.value) : undefined;
      } else if (record.type === 'daterange') {
        record.value =
          record.value && Array.isArray(record.value)
            ? record.value.map((it) => it && moment(it))
            : [];
      }

      Doms.push(record);
    }
    clink(klink);
    cbelink(belinked);
    cfilelist(defaultfiles);
    cDom(Doms);
    clen(allenin);
  }, [fields]);

  useEffect(() => {
    //联动数据
    for (let i in fields) {
      let extraprops = getSelectLinked(fields[i]);
      let { options } = extraprops;
      getOptions(options, fields[i]);
    }
  }, [link]);

  const getCol = (itemcol) => {
    if (itemcol) {
      return itemcol;
    } else {
      return col ? col : { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 12 };
    }
  };

  //下拉框联动声明
  const getSelectLinked = (item) => {
    let names = item.belinked && Object.keys(item.belinked),
      hides = item.hides,
      options = item.options;
    if (names && names.length > 0) {
      if (item.belinked.hides && item.belinked.hides.length > 0) {
        let requiredlist = item.belinked.hides
          .filter((it) => {
            return it.required;
          })
          .map((it) => {
            if (it.equalvalue) {
              let equalvalue =
                it.equalvalue && Array.isArray(it.equalvalue) && it.equalvalue.length > 0
                  ? it.equalvalue.indexOf(link[it.name]) != -1
                  : link[it.name] == it.equalvalue;
              return equalvalue;
            } else if (it.unequalvalue) {
              let unequalvalue =
                it.unequalvalue && Array.isArray(it.unequalvalue) && it.unequalvalue.length > 0
                  ? it.unequalvalue.indexOf(link[it.name]) == -1
                  : link[it.name] != it.unequalvalue;
              return unequalvalue;
            } else {
              return true;
            }
          });

        let unrequiredlist = item.belinked.hides
          .filter((it) => {
            return !it.required;
          })
          .map((it) => {
            if (it.equalvalue) {
              let equalvalue =
                it.equalvalue && Array.isArray(it.equalvalue) && it.equalvalue.length > 0
                  ? it.equalvalue.indexOf(link[it.name]) != -1
                  : link[it.name] == it.equalvalue;
              return equalvalue;
            } else if (it.unequalvalue) {
              let unequalvalue =
                it.unequalvalue && Array.isArray(it.unequalvalue) && it.unequalvalue.length > 0
                  ? it.unequalvalue.indexOf(link[it.name]) == -1
                  : link[it.name] != it.unequalvalue;
              return unequalvalue;
            } else {
              return true;
            }
          });
        let rq = requiredlist.some((it) => it == true);
        let unrq = unrequiredlist.some((it) => it == true);
        hides = hides ? hides : rq || unrq;
      }
      if (!Array.isArray(item.belinked.options) && item.belinked.options) {
        let { database, params } = item.belinked.options,
          newparams = {};
        //获取传参联动的值
        for (let i in params) {
          if (params[i] == 'linked') {
            newparams[i] = form.getFieldValue(i);
          } else {
            newparams[i] = params[i];
          }
        }
        if (Array.isArray(database)) {
          options = database;
        } else {
          options = {
            database,
            params: newparams,
          };
        }
      }
    }
    return {
      hides,
      options,
    };
  };

  //格式化数据提交
  function formartSubmit(values) {
    let newvalue = { ...values };
    for (let i in fields) {
      newvalue[i] = formartData(fields[i], values[i]);
    }
    submitData(newvalue, () => {
      form.resetFields();
    });
  }

  useEffect(() => {
    if (autoSubmit && len == ind) {
      setTimeout(() => {
        form
          .validateFields()
          .then((values) => {
            formartSubmit(values);
          })
          .catch((error) => {});
      }, 200);
    }
  }, [len, ind]);

  const submitBtn = (
    <Button
      style={{ width: '100%', marginTop: row ? 18 : 0 }}
      htmlType="submit"
      type="primary"
      size={row ? 'middle' : 'large'}
      disabled={submitting || loading}
      onClick={() => {
        form
          .validateFields()
          .then((values) => {
            sload(true);
            formartSubmit(values);
            setTimeout(() => {
              sload(false);
            }, 1000);
          })
          .catch((error) => {});
      }}
    >
      {submitting || loading ? <LoadingOutlined /> : null}
      {submitting || loading ? '' : '提交'}
    </Button>
  );

  let getOptions = async (options, item) => {
    let curkey = item.name[0];
    if (Array.isArray(options)) {
      if (JSON.stringify(optiondom[curkey]) !== JSON.stringify(options)) {
        cdom((optiondom) => {
          return {
            ...optiondom,
            [curkey]: options,
          };
        });
      }
    } else if (options?.database) {
      let { database, params } = options ? options : {},
        dom = [];
      if (Array.isArray(database)) {
        dom = database;
      } else {
        let res = await database(params),
          dataList = [];
        if (res.code == 0) {
          if (item.type == 'treeselect') {
            dataList = res?.data;
          } else {
            dataList = res?.data?.dataList
              ? res?.data?.dataList.map((it) => {
                  let label = item.formart ? item.formart[1] : 'name',
                    value = item.formart ? item.formart[0] : 'id';
                  return item.type == 'cascader'
                    ? it
                    : {
                        label: it[label],
                        value: it[value],
                      };
                })
              : [];
          }
        }

        dom = dataList;
      }
      if (JSON.stringify(optiondom[curkey]) !== JSON.stringify(dom)) {
        cdom((optiondom) => {
          return {
            ...optiondom,
            [curkey]: dom,
          };
        });
      }
    }
  };

  return (
    <div style={{ ...style, marginTop: -24 }} className="novia">
      <ConfigProvider locale={zhCN}>
        <Image
          src={cururl}
          width={0}
          height={0}
          preview={{
            visible,
            onVisibleChange: (visibles) => {
              if (visible) {
                setVisible(false);
              }
            },
          }}
        />
        <Form
          form={form}
          name="initform"
          layout={layout ? layout : 'vertical'}
          fields={Dom}
          onFinish={(values) => {
            //formartSubmit(values);
          }}
          onValuesChange={(changedValues, values) => {
            let newvalue = {};
            let linkkey = Object.keys(changedValues)[0];
            //联动逻辑
            for (let i in link) {
              if (i == linkkey) {
                clink({
                  ...link,
                  [i]: changedValues[i], //state修改当前value
                });
                //重置
                if (fields[i].linked) {
                  let keyarr = [];
                  for (let index in belink) {
                    if (
                      belink[index].options &&
                      Object.keys(belink[index].options.params).indexOf(i) != -1
                    ) {
                      keyarr.push(index);
                    }
                  }
                  keyarr.map((it) => form.setFieldsValue({ [it]: fields[it].multiple ? [] : '' }));
                }
              }
            }
            let allValues = form.getFieldsValue();
            for (let i in fields) {
              newvalue[i] = formartData(fields[i], allValues[i]);
              if (linkkey == i) {
                changedValues[i] = formartData(fields[i], allValues[i]);
              }
            }
            onChange && onChange(changedValues, newvalue);
          }}
        >
          <Row gutter={24} style={{ position: 'relative' }}>
            <Input type="text" name="userName" style={{ position: 'fixed', top: -999 }} />
            <Input type="password" style={{ position: 'fixed', top: -999 }} />
            {Dom.map((item, i) => {
              let extraprops = getSelectLinked(item);
              if (item.type == 'input' || item.type == 'password') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[
                        {
                          required: item.required,
                          message: `请输入${item.title}`,
                        },
                        {
                          validator: item.checkConfirm ? item.checkConfirm : null,
                        },
                        item.name[0].indexOf('phone') != -1
                          ? {
                              pattern: /^\d{11}$/,
                              message: '手机号格式不正确',
                            }
                          : item.name[0].indexOf('mail') != -1
                          ? {
                              pattern:
                                /^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-z]{2,}$/,
                              message: '邮箱格式不正确',
                            }
                          : {},
                      ]}
                    >
                      {item.type == 'password' ? (
                        <StrengthPwd mode={mode} item={item} />
                      ) : (
                        <Input
                          bordered={mode == 'simple' ? false : true}
                          className={mode == 'simple' ? 'simple' : ''}
                          placeholder={item.placeholder ? item.placeholder : item.title}
                          allowClear
                          type={item.type}
                          maxLength={500}
                          disabled={item.disabled}
                          addonAfter={
                            item.adresscharge ? (
                              <Tooltip title="获取经纬度">
                                <RetweetOutlined
                                  onClick={() => {
                                    let address = form.getFieldValue('address');
                                    fetch(
                                      'https://restapi.amap.com/v3/geocode/geo?key=e62898247d6cd9d2242b4894c35b94f8&address=' +
                                        address,
                                    )
                                      .then((res) => res.json())
                                      .then((result) => {
                                        if (result.geocodes[0]) {
                                          let locations = result.geocodes[0].location,
                                            lng = locations.split(',')[0],
                                            lat = locations.split(',')[1];

                                          form.setFieldsValue({ lng, lat });
                                        } else {
                                          message.error('无法识别该地址，请手动输入经纬度');
                                        }
                                      });
                                  }}
                                />
                              </Tooltip>
                            ) : null
                          }
                        />
                      )}
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'autoinput') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[
                        {
                          required: item.required,
                          message: `请输入${item.title}`,
                        },
                      ]}
                    >
                      <AutoComplete
                        allowClear
                        placeholder={item.placeholder ? item.placeholder : item.title}
                        disabled={item.disabled}
                        options={
                          optiondom[item.name[0]] &&
                          optiondom[item.name[0]].length > 0 &&
                          optiondom[item.name[0]]
                        }
                        bordered={mode == 'simple' ? false : true}
                        className={mode == 'simple' ? 'simple' : ''}
                        filterOption={(inputValue, option) => {
                          return option.value && option.value.toString().indexOf(inputValue) !== -1;
                        }}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'textarea') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请输入${item.title}` }]}
                    >
                      <Input.TextArea
                        maxLength={5000}
                        rows={4}
                        allowClear
                        placeholder={item.placeholder ? item.placeholder : item.title}
                        disabled={item.disabled}
                        bordered={mode == 'simple' ? false : true}
                        className={mode == 'simple' ? 'simple' : ''}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'select') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <Select
                        allowClear
                        placeholder={item.placeholder ? item.placeholder : item.title}
                        style={{ width: '100%' }}
                        showSearch
                        mode={item.multiple ? 'multiple' : ''}
                        filterOption={(input, option) =>
                          option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }
                        disabled={item.disabled}
                        maxTagCount={item.maxTagCount || 100}
                        bordered={mode == 'simple' ? false : true}
                        className={mode == 'simple' ? 'simple' : ''}
                      >
                        {optiondom[item.name[0]] &&
                          optiondom[item.name[0]].length > 0 &&
                          optiondom[item.name[0]]
                            .filter((it) => !it.hides)
                            .map((it, n) => {
                              return (
                                <Option
                                  disabled={it.disabled}
                                  key={n}
                                  value={it.dicKey ? it.dicKey : it.value}
                                >
                                  {it.dicName ? it.dicName : it.label}
                                </Option>
                              );
                            })}
                      </Select>
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'cascader') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <Cascader
                        fieldNames={item.fieldNames}
                        options={optiondom[item.name[0]]}
                        placeholder={item.placeholder ? item.placeholder : item.title}
                        style={{ width: '100%' }}
                        showSearch={{ filter }}
                        bordered={mode == 'simple' ? false : true}
                        disabled={item.disabled}
                        className={mode == 'simple' ? 'simple' : ''}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'radio') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <Radio.Group
                        disabled={item.disabled}
                        options={
                          optiondom[item.name[0]] &&
                          optiondom[item.name[0]].length > 0 &&
                          optiondom[item.name[0]]
                        }
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'datepicker') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <DatePicker
                        className={mode == 'simple' ? 'simple' : ''}
                        style={{ width: '100%' }}
                        disabledDate={item.disabledDate ? item.disabledDate : null}
                        disabledTime={item.disabledDateTime ? item.disabledDateTime : null}
                        showToday={true}
                        picker={item.picker}
                        showTime={item.showTime}
                        format={item.format}
                        disabled={item.disabled}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'daterange') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <RangePicker
                        className={mode == 'simple' ? 'simple' : ''}
                        style={{ width: '100%' }}
                        disabledDate={item.disabledDate ? item.disabledDate : null}
                        disabledTime={item.disabledDateTime ? item.disabledDateTime : null}
                        format={item.format}
                        showToday={true}
                        picker={item.picker}
                        showTime={item.showTime}
                        disabled={item.disabled}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'inputnumber') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请输入${item.title}` }]}
                    >
                      <InputNumber
                        bordered={mode == 'simple' ? false : true}
                        className={mode == 'simple' ? 'simple' : ''}
                        style={{ width: '100%' }}
                        disabled={item.disabled}
                        min={item.min ? item.min : 0}
                        max={item.max}
                        formatter={item.formatter}
                        parser={item.parser}
                      />
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'upload') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <UploadCom item={item} />
                    </Form.Item>
                    <div style={{ fontSize: 12, color: '#999', marginTop: 0, marginBottom: 36 }}>
                      {item.description || ''}
                    </div>
                  </Col>
                ) : null;
              } else if (item.type == 'treeselect') {
                let { title, key, children } = item.formart || {};
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    <Form.Item
                      style={{}}
                      label={item.title}
                      name={item.name[0]}
                      rules={[{ required: item.required, message: `请选择${item.title}` }]}
                    >
                      <TreeSelect
                        style={{ width: '100%' }}
                        dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                        disabled={item.disabled}
                        allowClear
                        showSearch={optiondom[item.name[0]] && optiondom[item.name[0]].length > 0}
                        multiple={item.multiple}
                        treeDefaultExpandAll
                        placeholder={item.placeholder ? item.placeholder : item.title}
                        filterTreeNode={(input, node) => {
                          return node.title.props.children.indexOf(input) != -1;
                        }}
                      >
                        {optiondom[item.name[0]] &&
                          optiondom[item.name[0]].length > 0 &&
                          loop(optiondom[item.name[0]], title, key, children)}
                      </TreeSelect>
                    </Form.Item>
                  </Col>
                ) : null;
              } else if (item.type == 'render') {
                return !extraprops.hides ? (
                  <Col key={i} {...getCol(item.col)}>
                    {item.render && item.render()}
                  </Col>
                ) : null;
              }
            })}

            <Col
              span={row ? 2 : reset ? 12 : 0}
              {...rowCol}
              style={{ padding: '12px', marginTop: row ? 18 : 0 }}
            >
              <Button
                size={row ? 'middle' : 'large'}
                style={{ width: '100%' }}
                onClick={() => {
                  form.resetFields();
                  form
                    .validateFields()
                    .then((values) => {
                      sload(true);
                      formartSubmit(values);
                      setTimeout(() => {
                        sload(false);
                      }, 1000);
                    })
                    .catch((error) => {});
                }}
              >
                重置
              </Button>
            </Col>
            <Col span={row ? 2 : reset ? 12 : 24} {...rowCol} style={{ padding: '12px' }}>
              {actions ? actions(form, submitBtn) : submitBtn}
            </Col>
            <Col span={24}>{children}</Col>
          </Row>
        </Form>
      </ConfigProvider>
    </div>
  );
};

export default memo(InitForm, (prev, next) => {
  if (prev.fields == next.fields) {
    return false;
  } else {
    return true;
  }
});
